package com.google.appengine.preferencessync.adapter;


import com.google.appengine.preferencessync.adapter.AbstractSyncablePrefsService;
import com.google.appengine.preferencessync.internal.CloudEndpointUtils;
import com.google.appengine.preferencessync.internal.Config;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.services.GoogleClient;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.jackson.JacksonFactory;

import com.appspot.api.services.deviceinfoendpoint.Deviceinfoendpoint;
import com.appspot.api.services.deviceinfoendpoint.model.DeviceInfo;
import com.appspot.api.services.syncendpoint.Syncendpoint;
import com.appspot.api.services.syncendpoint.model.Request;
import com.appspot.api.services.syncendpoint.model.Response;

import java.io.IOException;

/**
 * Extends AbstractSyncablePrefsService and calls cloud endpoint.
 */
public class SyncableSharedPrefsService extends AbstractSyncablePrefsService {
	  protected SyncResponse getResponse(String url, String reqtype, String payload)
			    throws Exception {  
    Config defaultConfig = Config.getDefaultConfig(getApplicationContext());
    if (!defaultConfig.isDeviceIdSent() && defaultConfig.getGCMRegistrationId() != null) {
      sendDeviceInfo(url);
    }

    return getSyncResponse(url, reqtype, payload);
  }
  
  private SyncResponse getSyncResponse(String url, String reqtype,
      String payload) throws IOException {

    Request request = new Request();
    request.setRequestType(reqtype);
    request.setPayload(payload);
    
    Syncendpoint.Builder syncEndpointBuilder = (Syncendpoint.Builder) updateBuilder(
        new Syncendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
            new HttpRequestInitializer() {
          public void initialize(HttpRequest httpRequest) {
          }
      }), url);

    Response response = syncEndpointBuilder.build().getSyncResponse(request).execute();

    return new SyncResponse(
      response.getResponseStr(), response.getConflict(), response.getInternalServerError());
  }

  private void sendDeviceInfo(String url) throws IOException {
    Config config = Config.getDefaultConfig(getApplicationContext());

    Deviceinfoendpoint.Builder deviceEndpointBuilder = (Deviceinfoendpoint.Builder) updateBuilder(
        new Deviceinfoendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
            new HttpRequestInitializer() {
          public void initialize(HttpRequest httpRequest) {
          }
      }), url);
    
    DeviceInfo deviceInfo = new DeviceInfo();
    deviceInfo.setUsername(config.getUsername());
    deviceInfo.setDeviceRegistrationID(config.getGCMRegistrationId());
    deviceInfo.setInitialDeviceRegistrationID(config.getGCMRegistrationId());
    deviceEndpointBuilder.build().insertDeviceInfo(deviceInfo).execute();

    config.setDeviceIdSent(true);
  }
  
  public static GoogleClient.Builder updateBuilder(GoogleClient.Builder builder, String url) {
    JsonHttpRequestInitializer jsonHttpRequestInitializer = new JsonHttpRequestInitializer() {
      public void initialize(JsonHttpRequest jsonHttpRequest) {
          jsonHttpRequest.setEnableGZipContent(false);
      }
    };

    builder.setJsonHttpRequestInitializer(jsonHttpRequestInitializer);
    
    if (url != null) {
      if (url.endsWith("/")) {
        url = url.substring(0,url.length()-1);
      }
      builder.setRootUrl(url + "/_ah/api/"); 
    } else {
      // else resort to CloudEndpointUtil's class.
      CloudEndpointUtils.updateBuilder(builder);
    }
    return builder;
  }
}
